﻿// lineDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "line.h"
#include "lineDlg.h"
#include "afxdialogex.h"
#include"util.h"
#include"authority.h"
#include"SQLexpression.h"
#include"index_manage.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

	// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// ClineDlg 对话框



ClineDlg::ClineDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(ClineDlg::IDD, pParent)
	, m_listenSocket(NULL)
	, m_port(0)
	, m_strNoUser(NULL)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}
ClineDlg::~ClineDlg() {
	delete m_strNoUser;
}

void ClineDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EventRecord, m_event);

	DDX_Control(pDX, IDC_USERLIST, m_users);
	DDX_Control(pDX, IDC_SERVERPORT, m_editPort);
	DDX_Control(pDX, IDC_SENDMSG, m_buttonSend);
}

BEGIN_MESSAGE_MAP(ClineDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BN_SERVER_START, &ClineDlg::startServer)
	//	ON_EN_CHANGE(IDC_EDIT2, &ClineDlg::OnEnChangeEdit2)
	ON_BN_CLICKED(IDC_SENDMSG, &ClineDlg::SendMSG)
	ON_BN_CLICKED(IDC_BUTTON2, &ClineDlg::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, &ClineDlg::OnBnClickedButton3)
END_MESSAGE_MAP()


// ClineDlg 消息处理程序

BOOL ClineDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO:  在此添加额外的初始化代码

	//----------------初始化------------------
	int n;
	CString noUser = _T("该用户不存在或者未上线");
	n = WideCharToMultiByte(CP_OEMCP, 0, noUser, -1, NULL, 0, 0, FALSE);
	m_strNoUser = new char[n];
	memset(m_strNoUser, 0, n*sizeof(char));
	WideCharToMultiByte(CP_OEMCP, 0, noUser.GetBuffer(0), n, m_strNoUser, n , 0, FALSE);
	m_connect = false;
	//设置“发送”按钮为不可用
	m_buttonSend.EnableWindow(FALSE);
	//----------------------------------------

	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void ClineDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}


// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void ClineDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR ClineDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

//启动/关闭服务器的服务
void ClineDlg::startServer(){
	//CString msg, info;string  smsg;
	//vector<insert_model> insert; insert_model m;
	//m.key = "id"; m.value = "3"; 
	//insert.push_back(m);
	//m.key = "name"; m.value = "wlcyuu1";
	//insert.push_back(m);
	////serverDb.Index_Create("test","id", smsg);
	//msg = smsg.c_str();
	//vector<char*>wh; wh.push_back("id"); wh.push_back("2"); wh.push_back("0");
	////serverDb.Table_Insert("test", insert, msg);
	//serverDb.Table_Select("test", insert, wh, info, msg);
	//AfxMessageBox(info);
	////serverDb.DB_Drop("db", msg);
	////serverDb.DB_Create("db", msg);
	////vector<char*>test; test.push_back("test"); test.push_back("id 1 8"); test.push_back("name 4 8");
	////serverDb.Table_Create(test, msg);
	//AfxMessageBox(msg);
	//return;
	// TODO:  在此添加控件通知处理程序代码
	
	CString cport;
	//获取服务器的端口号
	GetDlgItemText(IDC_SERVERPORT,cport);
	//端口号的字符串转换为数字
	int port = _ttoi(cport);
	//如果没有填写端口号，则默认的端口号为8080
	if (port == 0)
	{
		m_port = 8080;
	}
	else
	{
		m_port = port;
	}
	//如果当前服务器的状态为开启，则关闭服务器
	if (m_connect)
	{
		//关闭服务器的socket
		delete m_listenSocket;
		m_listenSocket = NULL;
		m_connect = false;
		SetDlgItemText(IDC_BN_SERVER_START, _T("打开服务器"));
		UpdateEvent(L"",_T("系统关闭服务器."));
		//关闭控件的只读状态
		m_editPort.SetReadOnly(FALSE);
		//设置“发送”按钮为不可用
		m_buttonSend.EnableWindow(FALSE);
		return;
	}
	//否则就打开服务器
	m_listenSocket = new CServerSocket();
	m_listenSocket->m_pDlg = this;
	m_listenSocket->m_userName = _T("服务器");
	// 指定对话框为主对话框，不能少了这句？
	UpdateData(true);
	// 创建服务器的套接字，IP地址默认本机IP
	if (!m_listenSocket->Create(m_port))
	{
		AfxMessageBox(_T("创建套接字错误！"));
		m_listenSocket->Close();
		return;
	}
	if (!m_listenSocket->Listen())
	{
		AfxMessageBox(_T("监听失败！"));
		m_listenSocket->Close();
		return;
	}
	m_connect = true;
	SetDlgItemText(IDC_BN_SERVER_START, _T("关闭服务器"));
	//更新聊天窗口中的消息
	UpdateEvent(L"",_T("系统打开服务器."));
	//将服务器端口号的控件设置为只读状态
	if(port == 0)
	{
		m_editPort.SetWindowTextW(_T("8080"));
	}
	else 
	{
		m_editPort.SetWindowTextW(cport);
	}
	m_editPort.SetReadOnly(TRUE);
	//设置“发送”按钮为可用
	m_buttonSend.EnableWindow(TRUE);
}

//接收由客户端发来的消息
void ClineDlg::RecvData(CServerSocket* pSocket)
{
	char* pData = NULL;
	pData = new char[1024];
	memset(pData, 0, sizeof(char)* 1024);
	UCHAR leng = 0;
	CString str;
	string userNameAndPwd;
	if (pSocket->Receive(pData, 1024, 0) != SOCKET_ERROR)
	{
		str = pData; 

		userNameAndPwd = pData;
		//登陆处理
		if(pSocket->m_userName==""){
			DoLogin(userNameAndPwd,pSocket);
		}else{
			CString name=pSocket->m_userName+"：";
			string log=UpdateEvent(name,str);
			//记录日志
			string LogPath = "data";
			if (pSocket->cur_db != "")
				LogPath = LogPath + "\\" + CStringTostring(pSocket->cur_db) + "\\" + CStringTostring(pSocket->cur_db);
			else
				LogPath = LogPath + "\\database";
			MyLogger(LogPath, log);
			//TODO 处理数据库操作
			SqlEx sql(pData);
			sql.check(pSocket,&serverDb, &authority);
		}
	}
	delete pData;
	pData = NULL;
}

int ClineDlg::DoLogin(string data,CServerSocket*Client_Socket){
	string UserName,pwd;
	int length = data.find("|");
	UserName = data.substr(0, length);
	pwd = data.substr(length+1,data.length()-length-1);
	CString ip; UINT port;
	Client_Socket->GetPeerName(ip, port);

	//TODO 登陆检查
	string user_host = "";
	bool auth=authority.Authentication(UserName, CStringTostring(ip), pwd,user_host);
	if(!auth){
		//登陆失败
		char* msg="userName or password is not correct !";
		Client_Socket->Send(msg,strlen(msg));
		//RemoveClient(Client_Socket);
		return -1;
	}

	//登陆成功
	Client_Socket->name=UserName;
	Client_Socket->host= CStringTostring(ip);
	CString name; 
	name = user_host.c_str();
	Client_Socket->m_userName = name;
	m_users.AddString(name);
	char msg[100]="Login successful !";
	Client_Socket->Send(msg,strlen(msg));
	return 1;
}

//移除已经退出连接的客户端
void ClineDlg::RemoveClient(CServerSocket* pSocket)
{
	POSITION nPos = m_clientList.GetHeadPosition();
	POSITION nTmpPos = nPos;
	//在客户端列表中查找该客户端
	while (nPos)
	{
		CServerSocket* pSockItem = (CServerSocket*)m_clientList.GetNext(nPos);
		//找到了就删除它
		if (pSockItem->m_hSocket == pSocket->m_hSocket)
		{
			CString userLeave;
			userLeave = pSockItem->m_userName;
			pSockItem->Close();
			delete pSockItem;
			int userIndex = m_users.FindString(0,userLeave);
			m_users.DeleteString(userIndex);
			m_clientList.RemoveAt(nTmpPos);
			m_userCount = m_clientList.GetCount();
			UpdateData(false);
			return;
		}
		nTmpPos = nPos;
	}
}

//更新聊天窗口中的内容
string ClineDlg::UpdateEvent(CString name,CString str)
{
	CString cstr;
	// 获取系统当前时间
	CTime time = CTime::GetCurrentTime();
	// 用于换行显示日志
	str += _T("\r\n");
	// 格式化当前时间
	cstr =name+ time.Format(_T("%Y/%m/%d %H:%M:%S  ")) + str;
	//获取编辑框最后一行索引
	long lastLine = m_event.LineIndex(m_event.GetLineCount() - 1);
	//选择编辑框最后一行
	m_event.SetSel(lastLine+1,lastLine+2,0);
	//替换所选那一行的内容
	m_event.ReplaceSel(cstr);
	return CStringTostring(cstr);
}

//添加新的客户端
void ClineDlg::AddClient()
{
	CServerSocket *pSocket = new CServerSocket;
	pSocket->m_pDlg = this;
	m_listenSocket->Accept(*pSocket);
	pSocket->AsyncSelect(FD_READ | FD_WRITE | FD_CLOSE);
	m_clientList.AddTail(pSocket);
	m_userCount = m_clientList.GetCount();
	UpdateData(false);
}

//断开连接
void ClineDlg::SendMSG()
{
	int selectIndex = m_users.GetCurSel();
	if(selectIndex == -1)
	{
		MessageBox(_T("请在连接列表中选择要断开的连接！"));
		return ;
	}
	CString usermsg;
	//获取该下标的字符串名称
	m_users.GetText(selectIndex, usermsg);
	POSITION nPos = m_clientList.GetHeadPosition();
	while (nPos){
		CServerSocket* pTemp = (CServerSocket*)m_clientList.GetNext(nPos);
		if(pTemp->m_userName==usermsg)
			RemoveClient(pTemp);
		break;
	}
}
//备份
void ClineDlg::OnBnClickedButton2()
{
	backup();
}

//还原
void ClineDlg::OnBnClickedButton3()
{
	DeleteDirectory(L"data");
	 Restore();
	// TODO: 在此添加控件通知处理程序代码
}
